import React, { useEffect, useCallback, useMemo, lazy, Suspense } from 'react'
import { connect } from 'react-redux'
import './App.css';
import URI from 'urijs'

import Header from '../common/Header.jsx';
import Nav from '../common/Nav.jsx';
import Detail from '../common/Detail.jsx';
import Candidate from './Candidate.jsx';
import useNav from '../common/useNav.js'
import { TrainContext } from './context'

import {
  setDepartStation,
  setArriveStation,
  setTrainNumber,
  setDepartDate,
  setSearchParsed,
  prevDate,
  nextDate,
  setDepartTimeStr,
  setArriveTimeStr,
  setArriveDate,
  setDurationStr,
  setTickets,
  toggleIsScheduleVisible,
} from './action.js';
import { h0 } from '../common/fp';
import dayjs from 'dayjs';
import { bindActionCreators } from 'redux';

const Schedule = lazy(() => import('./Schedule.jsx'))

function App(props) {
  const {
    departDate,
    arriveDate,
    departTimeStr,
    arriveTimeStr,
    departStation,
    arriveStation,
    trainNumber,
    durationStr,
    tickets,
    isScheduleVisible,
    searchParsed,
    dispatch,
  } = props;

  const onBack = useCallback(() => {
    window.history.back()
  }, [])

  useEffect(() => {
    // 页面加载，解析 URL
    const queries = URI.parseQuery(window.location.search)

    const {
      aStation,
      dStation,
      date,
      trainNumber
    } = queries

    dispatch(setDepartStation(dStation))
    dispatch(setArriveStation(aStation))
    dispatch(setTrainNumber(trainNumber))
    dispatch(setDepartDate(h0(dayjs(date).valueOf())))

    dispatch(setSearchParsed(true))

  }, [dispatch])

  useEffect(() => {
    document.title = trainNumber
  }, [trainNumber])

  useEffect(() => {
    if (!searchParsed) {
      return
    }

    const url = new URI('/rest/ticket')
      .setSearch('date', dayjs(departDate).format('YYYY-MM-DD'))
      .setSearch('trainNumber', trainNumber)
      .toString()

    fetch(url)
      .then(response => response.json())
      .then(result => {
        const {
          detail,
          candidates,
        } = result

        const {
          departTimeStr,
          arriveTimeStr,
          arriveDate,
          durationStr,
        } = detail

        dispatch(setDepartTimeStr(departTimeStr));
        dispatch(setArriveTimeStr(arriveTimeStr));
        dispatch(setArriveDate(arriveDate));
        dispatch(setDurationStr(durationStr));
        dispatch(setTickets(candidates));
      })
  }, [searchParsed, departDate, trainNumber, dispatch])

  const {
    isPrevDisabled,
    isNextDisabled,
    prev,
    next,
  } = useNav(departDate, dispatch, prevDate, nextDate)

  const detailCbs = useMemo(() => {
    return bindActionCreators({
      toggleIsScheduleVisible,
    }, dispatch)
  }, [dispatch])

  if (!searchParsed) {
    return null;
  }

  return (
    <div className="app">
      <div className="header-wrapper">
        <Header title={trainNumber} onBack={onBack} />
      </div>
      <div className="nav-wrapper">
        <Nav
          date={departDate}
          isPrevDisabled={isPrevDisabled}
          isNextDisabled={isNextDisabled}
          prev={prev}
          next={next}
        />
      </div>
      <div className="detail-wrapper">
        <Detail
          departDate={departDate}
          arriveDate={arriveDate}
          departTimeStr={departTimeStr}
          arriveTimeStr={arriveTimeStr}
          trainNumber={trainNumber}
          departStation={departStation}
          arriveStation={arriveStation}
          durationStr={durationStr}
        />
        <span className="left"></span>
        <span className="schedule" onClick={() => detailCbs.toggleIsScheduleVisible()}>时刻表</span>
        <span className="right"></span>
      </div>
      <TrainContext.Provider value={{ trainNumber, departStation, arriveStation, departDate }}>
        <Candidate tickets={tickets} />
      </TrainContext.Provider>
      {
        isScheduleVisible &&
        <div className="mask" onClick={() => dispatch(toggleIsScheduleVisible())}>
          <Suspense fallback={<div className="loading"><svg t="1623227017998" className="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2584" width="36" height="36"><path d="M552.421053 161.684211m-161.684211 0a161.684211 161.684211 0 1 0 323.368421 0 161.684211 161.684211 0 1 0-323.368421 0Z" fill="#fff" p-id="2585"></path><path d="M202.105263 377.263158m-134.736842 0a134.736842 134.736842 0 1 0 269.473684 0 134.736842 134.736842 0 1 0-269.473684 0Z" fill="#fff" opacity=".8" p-id="2586"></path><path d="M202.105263 727.578947m-107.789474 0a107.789474 107.789474 0 1 0 215.578948 0 107.789474 107.789474 0 1 0-215.578948 0Z" fill="#fff" opacity=".6" p-id="2587"></path><path d="M552.421053 943.157895m-80.842106 0a80.842105 80.842105 0 1 0 161.684211 0 80.842105 80.842105 0 1 0-161.684211 0Z" fill="#fff" opacity=".4" p-id="2588"></path><path d="M902.736842 727.578947m-53.894737 0a53.894737 53.894737 0 1 0 107.789474 0 53.894737 53.894737 0 1 0-107.789474 0Z" fill="#fff" opacity=".2" p-id="2589"></path><path d="M902.736842 350.315789m-26.947368 0a26.947368 26.947368 0 1 0 53.894737 0 26.947368 26.947368 0 1 0-53.894737 0Z" fill="#fff" opacity=".1" p-id="2590"></path></svg></div>}>
            <Schedule
              date={departDate}
              trainNumber={trainNumber}
              departStation={departStation}
              arriveStation={arriveStation}
            />
          </Suspense>
        </div>
      }
    </div>
  )
}

export default connect(
  function mapStateToProps(state) {
    return state;
  },
  function mapDispatchToProps(dispatch) {
    return { dispatch };
  }
)(App)
